package cc.bukkitPlugin.banitem.check;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import cc.bukkitPlugin.banitem.BanItemEnume.ListType;
import cc.bukkitPlugin.banitem.check.nbtvalue.ANBTValue;

public class Damage{

    public final short mValue;
    public final ListType mListType;
    private String mReason="";
    private HashMap<String,HashSet<ANBTValue>> mNBT=new HashMap<>();

    /*** 构造一个Damage实例*/
    public Damage(short mDamage,ListType pListType){
        this(mDamage,pListType,"该物品已被禁用");
    }

    /**
     * 构造一个Damage实例
     * @param mDamage Damage的值
     * @param pReason 被禁原因
     */
    public Damage(short mDamage,ListType pListType,String pReason){
        this.mValue=mDamage;
        this.mListType=pListType;
        if(this.isSimpleNode())
            this.mReason=null;
        else this.setReason(pReason);
    }

    /**
     * 检查该子id是否只是一个单纯的不包含原因和NBT的damage
     * @return
     */
    public boolean isSimpleNode(){
        return this.mListType.isSimpleNode();
    }

    public void setReason(String pReason){
        if(StringUtils.isEmpty(pReason))
            return;
        if(this.isSimpleNode())
            return;
        this.mReason=pReason;
    }

    /**
     * 获取原因
     * @return 非空或null
     */
    public String getReason(){
        return this.mReason;
    }

    /**
     * 检查指定NBT标中的指定值是否存在
     * <p>
     * 如果pNBTLabel为空,则直接为false<br />
     * </p>
     * @param pNBTLabel NBT标签
     * @return 是否存在
     */
    public boolean contains(String pNBTLabel){
        return this.contains(pNBTLabel,null);
    }

    /**
     * 检查指定NBT标中的指定值是否存在
     * <p>
     * 如果pNBTLabel为空,则直接为false<br />
     * 如果pNBTLabel不为空但是pNBTValue为null,直接为true
     * </p>
     * @param pNBTLabel NBT标签
     * @param pNBTRawValue NBT值
     * @return 是否存在
     */
    public boolean contains(String pNBTLabel,String pNBTRawValue){
        if(pNBTLabel==null)
            return false;
        HashSet<ANBTValue> nbtValues=this.mNBT.get(pNBTLabel);
        if(nbtValues==null)
            return false;
        else if(pNBTRawValue==null)
            return true;
        for(ANBTValue sValue : nbtValues)
            if(sValue.isInRange(pNBTRawValue))
                return true;
        return false;
    }

    /**
     * 添加指定的NBT标签的指定值
     * @param pNBTLabel NBT标签
     * @param pNBTRawValue NBT值
     * @return 是否成功添加
     */
    public boolean putNBTValue(String pNBTLabel,String pNBTRawValue){
        if(StringUtils.isEmpty(pNBTLabel)||StringUtils.isEmpty(pNBTRawValue))
            return false;
        if(this.contains(pNBTLabel,pNBTRawValue))
            return false;
        HashSet<ANBTValue> nbtValues=this.mNBT.get(pNBTLabel);
        if(nbtValues==null){
            nbtValues=new HashSet<>();
            this.mNBT.put(pNBTLabel,nbtValues);
        }
        nbtValues.add(ANBTValue.createNBTValue(pNBTRawValue));
        return true;
    }

    /**
     * 添加指定的NBT标签的指定值列表
     * <p>函数将合并已有的集合而不是覆盖</p>
     * @param pNBTLabel NBT标签
     * @param pNBTRawValues NBT值列表
     * @return 是否成功添加
     */
    public boolean putNBTValues(String pNBTLabel,List<String> pNBTRawValues){
        if(StringUtils.isEmpty(pNBTLabel)||pNBTRawValues==null)
            return false;
        HashSet<ANBTValue> nbtValues=this.mNBT.get(pNBTLabel);
        if(nbtValues==null){
            nbtValues=new HashSet<>();
            this.mNBT.put(pNBTLabel,nbtValues);
        }
        for(String sRawNBTValue : pNBTRawValues){
            nbtValues.add(ANBTValue.createNBTValue(sRawNBTValue));
        }
        return true;
    }

    /**
     * 添加指定的NBT标签的指定值列表
     * <p>函数将合并已有的集合而不是覆盖</p>
     * @param pNBTLabel NBT标签
     * @param pNBTValues NBT值列表
     * @return 是否成功添加
     */
    public boolean putNBTValues(String pNBTLabel,HashSet<ANBTValue> pNBTValues){
        if(StringUtils.isEmpty(pNBTLabel)||pNBTValues==null)
            return false;
        HashSet<ANBTValue> nbtValues=this.mNBT.get(pNBTLabel);
        if(nbtValues==null){
            nbtValues=new HashSet<>();
            this.mNBT.put(pNBTLabel,nbtValues);
        }
        nbtValues.addAll(pNBTValues);
        return true;
    }

    public HashSet<ANBTValue> removeNBTLabel(String pNBTLabel){
        if(StringUtils.isEmpty(pNBTLabel))
            return null;
        return this.mNBT.remove(pNBTLabel);
    }

    /**
     * 移除指定的NBT标签的指定值,如果移除后的NBT标签为空,将移除NBT标签
     * @param pNBTLabel NBT标签
     * @param pNBTRawValue NBT值
     * @return 是否移除添加
     */
    public boolean removeNBTValue(String pNBTLabel,String pNBTRawValue){
        if(StringUtils.isEmpty(pNBTLabel)||StringUtils.isEmpty(pNBTRawValue))
            return false;
        HashSet<ANBTValue> nbtValues=this.mNBT.get(pNBTLabel);
        if(nbtValues==null)
            return false;
        for(ANBTValue sValue : nbtValues)
            if(sValue.getRawValue().equals(pNBTRawValue)){
                nbtValues.remove(sValue);
                if(nbtValues.isEmpty())
                    this.mNBT.remove(pNBTLabel);
                return true;
            }
        return false;
    }

    /**
     * 获取NBT标签的Set集合的拷贝
     */
    public Set<String> getNBTLabelSet(){
        Set<String> tSet=new HashSet<>();
        tSet.addAll(this.mNBT.keySet());
        return tSet;
    }

    /**
     * 根据NBT标签获取NBT值列表
     * @param pNBTLabel NBT标签
     */
    public HashSet<ANBTValue> getNBTValues(String pNBTLabel){
        return this.mNBT.get(pNBTLabel);
    }

    /**
     * 根据NBT标签获取NBT值列表
     * @param pNBTLabel NBT标签
     */
    public HashSet<String> getRawNBTValues(String pNBTLabel){
        HashSet<ANBTValue> tNBTValues=this.mNBT.get(pNBTLabel);
        if(tNBTValues==null)
            return null;
        HashSet<String> tNBTRwaValues=new HashSet<>(tNBTValues.size());
        for(ANBTValue sValue : tNBTValues)
            tNBTRwaValues.add(sValue.getRawValue());
        return tNBTRwaValues;
    }

    /**
     * 特殊NBT标签是否为空
     */
    public boolean isEmpty(){
        return this.mNBT.isEmpty();
    }

}
